<?php
class Default_Model_Managers_Recipes extends Default_Model_Managers_EntityManagerAbstract
{  
	protected $_recipesDbTable;
	protected $_ingredientsDbTable;
	protected $_recipeHasIngredientsDbTable;
	protected $_foodTypesDbTable;
	protected $_recipeHasFoodTypeDbTable;
	protected $_themesDbTable;
	protected $_recipeHasThemes;
	
	protected $_recipesOnPage = 20;
	
    public function __construct()
    {
        $this->_recipesDbTable = new Default_Model_DbTable_Recipes;
        $this->_ingredientsDbTable = new Default_Model_DbTable_Ingredients;
        $this->_recipeHasIngredientsDbTable = new Default_Model_DbTable_RecipeHasIngredients;
        $this->_foodTypesDbTable = new Default_Model_DbTable_FoodTypes;
        $this->_recipeHasFoodTypeDbTable = new Default_Model_DbTable_RecipeHasFoodTypes;
        $this->_themesDbTable = new Default_Model_DbTable_Themes;
        $this->_recipeHasThemes = new Default_Model_DbTable_RecipeHasThemes;
    }
    
    public function addRecipe($data)
    {
    	$newName = "";
    	$newIngredientsName = "";
    	
        if ($data['photo']['error'] === 0) {
        	$newName = $this->getName($data['recipe_name']);
    		$this->uploadImage($data['photo'], $newName);
    	}
    	
    	if ($data['ingredientsPhoto']['error'] === 0) {
    		$newIngredientsName = $this->getName($data['recipe_name'])."_ingredients";
    		$this->uploadImage($data['ingredientsPhoto'], $newIngredientsName, "ingredients");
    	}
    	
    	$recipeData = array(
    		'recipe_name'       => $data['recipe_name'],
    		'process'           => $data['process'],
    		'photo'             => $newName,
    		'ingredients_photo' => $newIngredientsName,
    		'info'              => $data['info'],
    		'time'              => $data['time'],
    		'source'            => $data['source'],
    		'author_id'         => $data['author_id']
    	);
    	$recipeId = $this->_recipesDbTable->addRecipe($recipeData);
    	if ($recipeId != true){
    		return false;
    	}
    	$ingredientIds = $this->addIngredients($data['ingredients']);
    	if (!$this->addRecipeIngredients($recipeId, $ingredientIds)){
    		return false;
    	}
    	$foodTypeIds = $this->addFoodTypes($data['food_types']);
    	if (!$this->addRecipeFoodTypes($recipeId, $foodTypeIds)){
    		return false;
    	}
    	
    	$this->addRecipeThemes($recipeId, $data['themes']);
    	
    	return $recipeId;
    }
    
    protected function uploadImage($image, $newName, $imgType = "food")
    {
    	$imagesManager = new Default_Model_Managers_Images();
    	$imagesManager->resizeAndUpload(
    		700, 700, "images/".$imgType."/" . $newName . '.jpg', 95, "images/".$imgType."/original/" . $image['name']
    	);
    	$imagesManager->resizeAndUpload(
    		200, 200, "images/".$imgType."/" . $newName . '_small.jpg', 95, "images/".$imgType."/original/" . $image['name']
    	);
    }
    
    protected function getName($name)
    {
    	$cyr  = array(
    		'а','б','в','г','д','е','ж','з','и','й','к','л','м',
    		'н','о','п','р','с','т','у', 'ф','х','ц','ч','ш','щ',
    		'ъ', 'ы', 'ь', 'ю','я','А','Б','В','Г','Д','Е','Ж','З','И',
    		'Й','К','Л','М','Н','О','П','Р','С','Т','У', 'Ф','Х',
    		'Ц','Ч','Ш','Щ','Ъ','Ь', 'Ю','Я',' ',
    		'1','2','3','4','5','6','7','8','9','0'
    	);
		$lat = array(
			'a','b','v','g','d','e','zh','z','i','y','k','l','m',
			'n','o','p','r','s','t','u','f' ,'h' ,'ts' ,'ch','sh',
			'sht' ,'a', 'y' ,'y' ,'yu' ,'ya','A','B','V','G','D','E',
			'Zh','Z','I','Y','K','L','M','N','O','P','R','S','T',
			'U','F','H','Ts','Ch','Sh','Sht','A','Y','Yu','Ya','_',
			'1','2','3','4','5','6','7','8','9','0'
		);
		$newName = str_replace($cyr, $lat, $name);
    	return $newName;
    }
    
    protected function addIngredients($ingredientsList)
    {
    	$ingredientsList = mb_strtolower($ingredientsList);
    	$ingredients = $this->parseIngredients($ingredientsList);
    	
    	foreach($ingredients as $k => $ingredient){
    		$id = $this->_ingredientsDbTable->getIngredientId($ingredient[0]);
    		if( !isset($id['ingredient_id']) ) {
    			$ingredientName = preg_replace("/^\!/", "", $ingredient[0]);
    			$idgredientData = array(
	    			'ingredient_name' => $ingredientName
	    		);
	    		$ingredientId[$k] = $this->_ingredientsDbTable->addIngredient($idgredientData);
    		} else {
    			$ingredientId[$k] = $id['ingredient_id'];
    		}
    		$result[] = array(
    			'ingredient_id' => $ingredientId[$k],
    			'weight'        => $ingredient[1],
    			'is_main'        => $ingredient[2]
    		);
    	}
    	return $result;
    }
    
    protected function parseIngredients($ingredientsList)
    {
    	$ingredientsList = trim($ingredientsList);
    	$ingredientsArr = explode("\n", $ingredientsList);
    	foreach($ingredientsArr as $key => $ingredient) {
    		$ingredientArr = explode(":", $ingredient);
    		$ingredients[$key] = array_map( 
	    		create_function('$ingredient', 'return trim($ingredient);'),
	    		$ingredientArr
	    	);
    		if ($ingredients[$key][0][0] == "!") {
    			$ingredients[$key][0] = preg_replace("/^\!/", "", $ingredients[$key][0]);
    			$ingredients[$key][2] = 1;
    		} else {
    			$ingredients[$key][2] = 0;
    		}
    	}
    	return $ingredients;
    }
    
    protected function addFoodTypes($foodTypes)
    {
    	$foodTypes = mb_strtolower($foodTypes);
    	$foodTypesArr = $this->parseFoodTypes($foodTypes);
    	
    	foreach( $foodTypesArr as $k => $foodType ) {
    		$id = $this->_foodTypesDbTable->getFoodTypeId($foodType);
    		if( !isset($id['food_type_id']) ) {
    			$footTypeLatName = $this->getName($foodType);
    			$foodTypeData = array(
	    			'food_type_name'    => $foodType,
    				'food_type_latname' => $footTypeLatName
	    		);
	    		$foodTypeId[$k] = $this->_foodTypesDbTable->addFoodType($foodTypeData);
    		} else {
    			$foodTypeId[$k] = $id['food_type_id'];
    		}
    	}
    	return $foodTypeId;
    }
    
    protected function parseFoodTypes($foodTypes)
    {
    	$foodTypesArr = explode(",", $foodTypes);
    	$foodTypesArr = array_map( 
    		create_function('$foodType', 'return trim($foodType);'),
    		$foodTypesArr
    	);
    	
    	return $foodTypesArr;
    }
    
    protected function addRecipeFoodTypes($recipeId, $foodTypeIds)
    {
    	foreach ($foodTypeIds as $foodTypeId) {
    		$data = array(
    			'recipe_id'    => $recipeId,
    			'food_type_id' => $foodTypeId
    		);
    		if (!$this->_recipeHasFoodTypeDbTable->addRecipeFoodTypes($data)) {
    			return false;
    		}
    	}
    	return true;
    }
    
    protected function addRecipeIngredients($recipeId, $ingredientIds)
    {
    	foreach ($ingredientIds as $k => $ingredient) {
    		$data = $ingredient;
    		$data['recipe_id'] = $recipeId;
    		if (!$this->_recipeHasIngredientsDbTable->addRecipeIngredients($data)) {
    			return false;
    		}
    	}
    	return true;
    }
    
    public function getRecipeById($recipeId)
    {
    	$recipe = $this->_recipesDbTable->getRecipeById($recipeId);
    	$data = $recipe->toArray();
    	
    	$ingredients = $this->_recipeHasIngredientsDbTable->getIngredientsByRecipeId($recipeId);
    	
    	$ingredientString = "";
    	foreach ($ingredients as $ingredient) {
    		if ($ingredient['is_main'] == 1) {
    			$main = "!";
    		} else {
    			$main = "";
    		}
    		$ingredientString .= $main.$ingredient['ingredient_name'].': '.$ingredient['weight']."\n";  
    	}
    	
    	$foodTypes = $this->_recipeHasFoodTypeDbTable->getFoodTypesByRecipeId($recipeId);
    	
    	foreach ($foodTypes as $foodType) {
    		$foodTypeArr[] = $foodType['food_type_name'];  
    	}
    	$foodTypeString = implode(", ", $foodTypeArr);
    	
    	$data['ingredients'] = $ingredientString;
    	$data['ingredientsArray'] = $this->parseIngredients($ingredientString);
    	$data['food_types'] = $foodTypeString;
    	$recipeThemes = $this->_recipeHasThemes->getRecipeThemes($recipeId)->toArray();
    	foreach ($recipeThemes as $theme) {
    		$themesArr[] = $theme['theme_id'];;
    	}
    	//var_dump($recipeThemes);
    	$data['themes'] = $themesArr; 

    	return $data;
    }
    
    public function updateRecipe($data)
    {
    	$recipeId = $data['id'];
    	$recipeData = array();
    	
    	if ($data['photo']['error'] === 0) {
    		$newName = $this->getName($data['recipe_name']);
    		$this->uploadImage($data['photo'], $newName);
    		$recipeData['photo'] = $newName;
    	}
        if ($data['ingredientsPhoto']['error'] === 0) {
    		$newIngredientsName = $this->getName($data['recipe_name']) . "_ingredients";
    		$this->uploadImage($data['ingredientsPhoto'], $newIngredientsName, "ingredients");
    		$recipeData['ingredients_photo'] = $newIngredientsName;
    	}
    	
    	$newName = $this->getName($data['recipe_name']);
    	$newIngredientsName = $this->getName($data['recipe_name']) . "_ingredients";
    	$recipeData = $recipeData + array(
    		'recipe_name' => $data['recipe_name'],
    		'process'     => $data['process'],
    		'info'        => $data['info'],
    		'time'        => $data['time'],
    		'source'      => $data['source'],
    		'author_id'   => $data['author_id']
    	);
    	
    	$this->_recipesDbTable->updateRecipe($recipeData, $recipeId);
    	
    	$this->_recipeHasIngredientsDbTable->deleteIngredients($data['id']);

    	$ingredientIds = $this->addIngredients($data['ingredients']);

    	if (!$this->addRecipeIngredients($recipeId, $ingredientIds)){
    		return false;
    	}
    	
    	$this->_recipeHasFoodTypeDbTable->deleteFoodTypes($data['id']);
    	
    	$foodTypeIds = $this->addFoodTypes($data['food_types']);
    	if (!$this->addRecipeFoodTypes($recipeId, $foodTypeIds)){
    		return false;
    	}
    	
    	$this->_recipeHasThemes->deleteRecipeFromTheme($recipeId);
    	$this->addRecipeThemes($recipeId, $data['themes']);
    }
    
    public function getRecipesList($foodType = "all", $page = 1)
    {
    	$offset = $page * $this->_recipesOnPage - $this->_recipesOnPage; 
    	$recipes = $this->_recipesDbTable->getRecipesList($foodType, $this->_recipesOnPage, $offset);
    	
    	foreach ($recipes as $id => $recipe) {
    		$recipes[$id]['ingredients'] = $this->_recipeHasIngredientsDbTable->getIngredientsByRecipeId($recipe['recipe_id']);
    	}
    	
    	return $recipes;
    }
    
    public function getRecipesByIngredient($ingredient, $page)
    {
    	$offset = $page * $this->_recipesOnPage - $this->_recipesOnPage; 
    	$recipes = $this->_recipesDbTable->getRecipesByIngredient($ingredient, $this->_recipesOnPage, $offset);
    	
    	foreach ($recipes as $id => $recipe) {
    		$recipes[$id]['ingredients'] = $this->_recipeHasIngredientsDbTable->getIngredientsByRecipeId($recipe['recipe_id']);
    	}
    	
    	return $recipes;
    }
    
    public function getPagesCount($foodType = "all")
    {
    	$recipesCount = $this->_recipesDbTable->getRecipesCount($foodType);
    	$pagesCount = ceil($recipesCount/$this->_recipesOnPage);
    	return $pagesCount;
    }
    
    public function getPagesCountByIngredient($ingredient)
    {
    	$recipesCount = $this->_recipesDbTable->getRecipesCountByIngredient($ingredient);
    	$pagesCount = ceil($recipesCount/$this->_recipesOnPage);
    	return $pagesCount;
    }
    
	public function getFoodTypes($minCount = 0)
    {
    	$foodTypes = $this->_foodTypesDbTable->getFoodTypes($minCount);
    	return $foodTypes;
    }
    
    public function getFoodTypeName($foodType)
    {
    	$foodTypeName = $this->_foodTypesDbTable->getFoodTypeName($foodType);
    	return $foodTypeName['food_type_name'];
    }
    
    public function getMainIngredients()
    {
    	$mainIngredients = $this->_recipeHasIngredientsDbTable->getMainIngredients();
    	
    	foreach ($mainIngredients as $ingredient) {
    		$counts[] = $ingredient['count'];
    	}
    	
    	$max = max($counts);
    	$m = 255-16*3;
		$step = $max/$m/2;
    	
    	foreach ($mainIngredients as $key => $ingredient) {
	    	$h = ceil($ingredient['count']/$step);
		    $hd = $m - $h;
		    $hd = dechex($hd);
		    if (strlen($hd) == 1) {
		     $hd = "0".$hd;
		    }
		    if (hexdec($hd)>255) {
		        $hd = "00";
		    }
		    $mainIngredients[$key]['color'] = $hd;
    	}
    	return $mainIngredients;
    }
    
    public function getAllThemes()
    {
    	$themes = $this->_themesDbTable->getThemes();
    	return $themes->toArray();
    }
    
    private function addRecipeThemes($recipeId, $themes)
    {
        if ($themes > 0) {
	        foreach($themes as $theme){
	    		$recipeThemes = array(
	    			'recipe_id' => $recipeId,
	    			'theme_id' => $theme
	    		);
	    		$this->_recipeHasThemes->addThemeRecipes($recipeThemes);
	    	}
    	}
    }
}